home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tk8.0 / generic / tkUtil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  10.3 KB  |  349 lines  |  [TEXT/CWIE]

  1. /* 
  2.  * tkUtil.c --
  3.  *
  4.  *    This file contains miscellaneous utility procedures that
  5.  *    are used by the rest of Tk, such as a procedure for drawing
  6.  *    a focus highlight.
  7.  *
  8.  * Copyright (c) 1994 The Regents of the University of California.
  9.  * Copyright (c) 1994-1995 Sun Microsystems, Inc.
  10.  *
  11.  * See the file "license.terms" for information on usage and redistribution
  12.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  13.  *
  14.  * SCCS: @(#) tkUtil.c 1.13 97/06/06 11:16:22
  15.  */
  16.  
  17. #include "tkInt.h"
  18. #include "tkPort.h"
  19.  
  20. /*
  21.  *----------------------------------------------------------------------
  22.  *
  23.  * TkDrawInsetFocusHighlight --
  24.  *
  25.  *    This procedure draws a rectangular ring around the outside of
  26.  *    a widget to indicate that it has received the input focus.  It
  27.  *    takes an additional padding argument that specifies how much
  28.  *    padding is present outside th widget.
  29.  *
  30.  * Results:
  31.  *    None.
  32.  *
  33.  * Side effects:
  34.  *    A rectangle "width" pixels wide is drawn in "drawable",
  35.  *    corresponding to the outer area of "tkwin".
  36.  *
  37.  *----------------------------------------------------------------------
  38.  */
  39.  
  40. void
  41. TkDrawInsetFocusHighlight(tkwin, gc, width, drawable, padding)
  42.     Tk_Window tkwin;        /* Window whose focus highlight ring is
  43.                  * to be drawn. */
  44.     GC gc;            /* Graphics context to use for drawing
  45.                  * the highlight ring. */
  46.     int width;            /* Width of the highlight ring, in pixels. */
  47.     Drawable drawable;        /* Where to draw the ring (typically a
  48.                  * pixmap for double buffering). */
  49.     int padding;        /* Width of padding outside of widget. */
  50. {
  51.     XRectangle rects[4];
  52.  
  53.     /*
  54.      * On the Macintosh the highlight ring needs to be "padded"
  55.      * out by one pixel.  Unfortunantly, none of the Tk widgets
  56.      * had a notion of padding between the focus ring and the
  57.      * widget.  So we add this padding here.  This introduces
  58.      * two things to worry about:
  59.      *
  60.      * 1) The widget must draw the background color covering
  61.      *    the focus ring area before calling Tk_DrawFocus.
  62.      * 2) It is impossible to draw a focus ring of width 1.
  63.      *    (For the Macintosh Look & Feel use width of 3)
  64.      */
  65. #ifdef MAC_TCL
  66.     width--;
  67. #endif
  68.  
  69.     rects[0].x = padding;
  70.     rects[0].y = padding;
  71.     rects[0].width = Tk_Width(tkwin) - (2 * padding);
  72.     rects[0].height = width;
  73.     rects[1].x = padding;
  74.     rects[1].y = Tk_Height(tkwin) - width - padding;
  75.     rects[1].width = Tk_Width(tkwin) - (2 * padding);
  76.     rects[1].height = width;
  77.     rects[2].x = padding;
  78.     rects[2].y = width + padding;
  79.     rects[2].width = width;
  80.     rects[2].height = Tk_Height(tkwin) - 2*width - 2*padding;
  81.     rects[3].x = Tk_Width(tkwin) - width - padding;
  82.     rects[3].y = rects[2].y;
  83.     rects[3].width = width;
  84.     rects[3].height = rects[2].height;
  85.     XFillRectangles(Tk_Display(tkwin), drawable, gc, rects, 4);
  86. }
  87.  
  88. /*
  89.  *----------------------------------------------------------------------
  90.  *
  91.  * Tk_DrawFocusHighlight --
  92.  *
  93.  *    This procedure draws a rectangular ring around the outside of
  94.  *    a widget to indicate that it has received the input focus.
  95.  *
  96.  * Results:
  97.  *    None.
  98.  *
  99.  * Side effects:
  100.  *    A rectangle "width" pixels wide is drawn in "drawable",
  101.  *    corresponding to the outer area of "tkwin".
  102.  *
  103.  *----------------------------------------------------------------------
  104.  */
  105.  
  106. void
  107. Tk_DrawFocusHighlight(tkwin, gc, width, drawable)
  108.     Tk_Window tkwin;        /* Window whose focus highlight ring is
  109.                  * to be drawn. */
  110.     GC gc;            /* Graphics context to use for drawing
  111.                  * the highlight ring. */
  112.     int width;            /* Width of the highlight ring, in pixels. */
  113.     Drawable drawable;        /* Where to draw the ring (typically a
  114.                  * pixmap for double buffering). */
  115. {
  116.     TkDrawInsetFocusHighlight(tkwin, gc, width, drawable, 0);
  117. }
  118.  
  119. /*
  120.  *----------------------------------------------------------------------
  121.  *
  122.  * Tk_GetScrollInfo --
  123.  *
  124.  *    This procedure is invoked to parse "xview" and "yview"
  125.  *    scrolling commands for widgets using the new scrolling
  126.  *    command syntax ("moveto" or "scroll" options).
  127.  *
  128.  * Results:
  129.  *    The return value is either TK_SCROLL_MOVETO, TK_SCROLL_PAGES,
  130.  *    TK_SCROLL_UNITS, or TK_SCROLL_ERROR.  This indicates whether
  131.  *    the command was successfully parsed and what form the command
  132.  *    took.  If TK_SCROLL_MOVETO, *dblPtr is filled in with the
  133.  *    desired position;  if TK_SCROLL_PAGES or TK_SCROLL_UNITS,
  134.  *    *intPtr is filled in with the number of lines to move (may be
  135.  *    negative);  if TK_SCROLL_ERROR, interp->result contains an
  136.  *    error message.
  137.  *
  138.  * Side effects:
  139.  *    None.
  140.  *
  141.  *----------------------------------------------------------------------
  142.  */
  143.  
  144. int
  145. Tk_GetScrollInfo(interp, argc, argv, dblPtr, intPtr)
  146.     Tcl_Interp *interp;            /* Used for error reporting. */
  147.     int argc;                /* # arguments for command. */
  148.     char **argv;            /* Arguments for command. */
  149.     double *dblPtr;            /* Filled in with argument "moveto"
  150.                      * option, if any. */
  151.     int *intPtr;            /* Filled in with number of pages
  152.                      * or lines to scroll, if any. */
  153. {
  154.     int c;
  155.     size_t length;
  156.  
  157.     length = strlen(argv[2]);
  158.     c = argv[2][0];
  159.     if ((c == 'm') && (strncmp(argv[2], "moveto", length) == 0)) {
  160.     if (argc != 4) {
  161.         Tcl_AppendResult(interp, "wrong # args: should be \"",
  162.             argv[0], " ", argv[1], " moveto fraction\"",
  163.             (char *) NULL);
  164.         return TK_SCROLL_ERROR;
  165.     }
  166.     if (Tcl_GetDouble(interp, argv[3], dblPtr) != TCL_OK) {
  167.         return TK_SCROLL_ERROR;
  168.     }
  169.     return TK_SCROLL_MOVETO;
  170.     } else if ((c == 's')
  171.         && (strncmp(argv[2], "scroll", length) == 0)) {
  172.     if (argc != 5) {
  173.         Tcl_AppendResult(interp, "wrong # args: should be \"",
  174.             argv[0], " ", argv[1], " scroll number units|pages\"",
  175.             (char *) NULL);
  176.         return TK_SCROLL_ERROR;
  177.     }
  178.     if (Tcl_GetInt(interp, argv[3], intPtr) != TCL_OK) {
  179.         return TK_SCROLL_ERROR;
  180.     }
  181.     length = strlen(argv[4]);
  182.     c = argv[4][0];
  183.     if ((c == 'p') && (strncmp(argv[4], "pages", length) == 0)) {
  184.         return TK_SCROLL_PAGES;
  185.     } else if ((c == 'u')
  186.         && (strncmp(argv[4], "units", length) == 0)) {
  187.         return TK_SCROLL_UNITS;
  188.     } else {
  189.         Tcl_AppendResult(interp, "bad argument \"", argv[4],
  190.             "\": must be units or pages", (char *) NULL);
  191.         return TK_SCROLL_ERROR;
  192.     }
  193.     }
  194.     Tcl_AppendResult(interp, "unknown option \"", argv[2],
  195.         "\": must be moveto or scroll", (char *) NULL);
  196.     return TK_SCROLL_ERROR;
  197. }
  198.  
  199. /*
  200.  *---------------------------------------------------------------------------
  201.  *
  202.  * TkComputeAnchor --
  203.  *
  204.  *    Determine where to place a rectangle so that it will be properly
  205.  *    anchored with respect to the given window.  Used by widgets
  206.  *    to align a box of text inside a window.  When anchoring with
  207.  *    respect to one of the sides, the rectangle be placed inside of
  208.  *    the internal border of the window.
  209.  *
  210.  * Results:
  211.  *    *xPtr and *yPtr set to the upper-left corner of the rectangle
  212.  *    anchored in the window.
  213.  *
  214.  * Side effects:
  215.  *    None.
  216.  *
  217.  *---------------------------------------------------------------------------
  218.  */
  219. void
  220. TkComputeAnchor(anchor, tkwin, padX, padY, innerWidth, innerHeight, xPtr, yPtr)
  221.     Tk_Anchor anchor;        /* Desired anchor. */
  222.     Tk_Window tkwin;        /* Anchored with respect to this window. */
  223.     int padX, padY;        /* Use this extra padding inside window, in
  224.                  * addition to the internal border. */
  225.     int innerWidth, innerHeight;/* Size of rectangle to anchor in window. */
  226.     int *xPtr, *yPtr;        /* Returns upper-left corner of anchored
  227.                  * rectangle. */
  228. {
  229.     switch (anchor) {
  230.     case TK_ANCHOR_NW:
  231.     case TK_ANCHOR_W:
  232.     case TK_ANCHOR_SW:
  233.         *xPtr = Tk_InternalBorderWidth(tkwin) + padX;
  234.         break;
  235.  
  236.     case TK_ANCHOR_N:
  237.     case TK_ANCHOR_CENTER:
  238.     case TK_ANCHOR_S:
  239.         *xPtr = (Tk_Width(tkwin) - innerWidth) / 2;
  240.         break;
  241.  
  242.     default:
  243.         *xPtr = Tk_Width(tkwin) - (Tk_InternalBorderWidth(tkwin) + padX)
  244.             - innerWidth;
  245.         break;
  246.     }
  247.  
  248.     switch (anchor) {
  249.     case TK_ANCHOR_NW:
  250.     case TK_ANCHOR_N:
  251.     case TK_ANCHOR_NE:
  252.         *yPtr = Tk_InternalBorderWidth(tkwin) + padY;
  253.         break;
  254.  
  255.     case TK_ANCHOR_W:
  256.     case TK_ANCHOR_CENTER:
  257.     case TK_ANCHOR_E:
  258.         *yPtr = (Tk_Height(tkwin) - innerHeight) / 2;
  259.         break;
  260.  
  261.     default:
  262.         *yPtr = Tk_Height(tkwin) - Tk_InternalBorderWidth(tkwin) - padY
  263.             - innerHeight;
  264.         break;
  265.     }
  266. }
  267.  
  268. /*
  269.  *---------------------------------------------------------------------------
  270.  *
  271.  * TkFindStateString --
  272.  *
  273.  *    Given a lookup table, map a number to a string in the table.
  274.  *
  275.  * Results:
  276.  *    If numKey was equal to the numeric key of one of the elements
  277.  *    in the table, returns the string key of that element.
  278.  *    Returns NULL if numKey was not equal to any of the numeric keys
  279.  *    in the table.
  280.  *
  281.  * Side effects.
  282.  *    None.
  283.  *
  284.  *---------------------------------------------------------------------------
  285.  */
  286.  
  287. char *
  288. TkFindStateString(mapPtr, numKey)
  289.     CONST TkStateMap *mapPtr;    /* The state table. */
  290.     int numKey;            /* The key to try to find in the table. */
  291. {
  292.     for ( ; mapPtr->strKey != NULL; mapPtr++) {
  293.     if (numKey == mapPtr->numKey) {
  294.         return mapPtr->strKey;
  295.     }
  296.     }
  297.     return NULL;
  298. }
  299.  
  300. /*
  301.  *---------------------------------------------------------------------------
  302.  *
  303.  * TkFindStateNum --
  304.  *
  305.  *    Given a lookup table, map a string to a number in the table.
  306.  *
  307.  * Results:
  308.  *    If strKey was equal to the string keys of one of the elements
  309.  *    in the table, returns the numeric key of that element.
  310.  *    Returns the numKey associated with the last element (the NULL
  311.  *    string one) in the table if strKey was not equal to any of the
  312.  *    string keys in the table.  In that case, an error message is
  313.  *    also left in interp->result (if interp is not NULL).
  314.  *
  315.  * Side effects.
  316.  *    None.
  317.  *
  318.  *---------------------------------------------------------------------------
  319.  */
  320.  
  321. int
  322. TkFindStateNum(interp, field, mapPtr, strKey)
  323.     Tcl_Interp *interp;        /* Interp for error reporting. */
  324.     CONST char *field;        /* String to use when constructing error. */
  325.     CONST TkStateMap *mapPtr;    /* Lookup table. */
  326.     CONST char *strKey;        /* String to try to find in lookup table. */
  327. {
  328.     CONST TkStateMap *mPtr;
  329.  
  330.     if (mapPtr->strKey == NULL) {
  331.     panic("TkFindStateNum: no choices in lookup table");
  332.     }
  333.  
  334.     for (mPtr = mapPtr; mPtr->strKey != NULL; mPtr++) {
  335.     if (strcmp(strKey, mPtr->strKey) == 0) {
  336.         return mPtr->numKey;
  337.     }
  338.     }
  339.     if (interp != NULL) {
  340.     mPtr = mapPtr;
  341.     Tcl_AppendResult(interp, "bad ", field, " value \"", strKey,
  342.         "\": must be ", mPtr->strKey, (char *) NULL);
  343.     for (mPtr++; mPtr->strKey != NULL; mPtr++) {
  344.         Tcl_AppendResult(interp, ", ", mPtr->strKey, (char *) NULL);
  345.     }
  346.     }
  347.     return mPtr->numKey;
  348. }
  349.